#include "BindWindow.hpp"

using namespace luabind;
namespace bind
{
	namespace SFML
	{
		namespace window
		{
			void BContext(lua_State* lua, const std::string& ns)
			{
				module(lua, ns.c_str())
					[
						class_<sf::Context>("Context")
							.def(constructor<>())
							.def("SetActive", &sf::Context::SetActive)
							.def("SetReferenceActive", &sf::Context::SetReferenceActive)
					];
			}

			void BContextSettings(lua_State* lua, const std::string& ns)
			{
				module(lua, ns.c_str())
					[
						class_<sf::ContextSettings>("ContextSettings")
							.def(constructor<unsigned int, unsigned int, unsigned int, unsigned int, unsigned int>())
							.def_readwrite("DepthBits", &sf::ContextSettings::DepthBits)
							.def_readwrite("StencilBits", &sf::ContextSettings::StencilBits)
							.def_readwrite("AntialiasingLevel", &sf::ContextSettings::AntialiasingLevel)
							.def_readwrite("MajorVersion", &sf::ContextSettings::MajorVersion)
							.def_readwrite("MinorVersion", &sf::ContextSettings::MinorVersion)
					];
			}
			
			void BEvent(lua_State* lua, const std::string& ns)
			{
				module(lua, ns.c_str())
					[
						class_<sf::Event>("Event")
							.def(constructor<>())
							.def_readwrite("Type", &sf::Event::Type)
							.def_readwrite("Key", &sf::Event::Key)
							.def_readwrite("Text", &sf::Event::Text)
							.def_readwrite("MouseMove", &sf::Event::MouseMove)
							.def_readwrite("MouseButton", &sf::Event::MouseButton)
							.def_readwrite("MouseWheel", &sf::Event::MouseWheel)
							.def_readwrite("JoyMove", &sf::Event::JoyMove)
							.def_readwrite("JoyButton", &sf::Event::JoyButton)
							.def_readwrite("Size", &sf::Event::Size)
							.def_readwrite("Type", &sf::Event::Type),

						class_<sf::Event::KeyEvent>("KeyEvent")
							.def_readwrite("Code", &sf::Event::KeyEvent::Code)
							.def_readwrite("Alt", &sf::Event::KeyEvent::Alt)
							.def_readwrite("Control", &sf::Event::KeyEvent::Control)
							.def_readwrite("Shift", &sf::Event::KeyEvent::Shift),

						class_<sf::Event::TextEvent>("TextEvent")
							.def_readwrite("Unicode", &sf::Event::TextEvent::Unicode),

						class_<sf::Event::MouseMoveEvent>("MouseMoveEvent")
							.def_readwrite("X", &sf::Event::MouseMoveEvent::X)
							.def_readwrite("Y", &sf::Event::MouseMoveEvent::Y),

						class_<sf::Event::MouseButtonEvent>("MouseButtonEvent")
							.def_readwrite("Button", &sf::Event::MouseButtonEvent::Button)
							.def_readwrite("X", &sf::Event::MouseButtonEvent::X)
							.def_readwrite("Y", &sf::Event::MouseButtonEvent::Y),

						class_<sf::Event::MouseWheelEvent>("MouseWheelEvent")
							.def_readwrite("Delta", &sf::Event::MouseWheelEvent::Delta)
							.def_readwrite("X", &sf::Event::MouseWheelEvent::X)
							.def_readwrite("Y", &sf::Event::MouseWheelEvent::Y),

						class_<sf::Event::JoyMoveEvent>("JoyMoveEvent")
							.def_readwrite("JoystickId", &sf::Event::JoyMoveEvent::JoystickId)
							.def_readwrite("Axis", &sf::Event::JoyMoveEvent::Axis)
							.def_readwrite("Position", &sf::Event::JoyMoveEvent::Position),

						class_<sf::Event::JoyButtonEvent>("JoyButtonEvent")
							.def_readwrite("JoystickId", &sf::Event::JoyButtonEvent::JoystickId)
							.def_readwrite("Button", &sf::Event::JoyButtonEvent::Button),

						class_<sf::Event::SizeEvent>("SizeEvent")
							.def_readwrite("Width", &sf::Event::SizeEvent::Width)
							.def_readwrite("Height", &sf::Event::SizeEvent::Height)
					];

					object key = newtable(lua);
					key["A"] = sf::Key::Code::A;
					key["B"] = sf::Key::Code::B;
					key["C"] = sf::Key::Code::C;
					key["D"] = sf::Key::Code::D;
					key["E"] = sf::Key::Code::E;
					key["F"] = sf::Key::Code::F;
					key["G"] = sf::Key::Code::G;
					key["H"] = sf::Key::Code::H;
					key["I"] = sf::Key::Code::I;
					key["J"] = sf::Key::Code::J;
					key["K"] = sf::Key::Code::K;
					key["L"] = sf::Key::Code::L;
					key["M"] = sf::Key::Code::M;
					key["N"] = sf::Key::Code::N;
					key["O"] = sf::Key::Code::O;
					key["P"] = sf::Key::Code::P;
					key["Q"] = sf::Key::Code::Q;
					key["R"] = sf::Key::Code::R;
					key["S"] = sf::Key::Code::S;
					key["T"] = sf::Key::Code::T;
					key["U"] = sf::Key::Code::U;
					key["V"] = sf::Key::Code::V;
					key["W"] = sf::Key::Code::W;
					key["X"] = sf::Key::Code::X;
					key["Y"] = sf::Key::Code::Y;
					key["Z"] = sf::Key::Code::Z;
					key["Num0"] = sf::Key::Code::Num0;
					key["Num1"] = sf::Key::Code::Num1;
					key["Num2"] = sf::Key::Code::Num2;
					key["Num3"] = sf::Key::Code::Num3;
					key["Num4"] = sf::Key::Code::Num4;
					key["Num5"] = sf::Key::Code::Num5;
					key["Num6"] = sf::Key::Code::Num6;
					key["Num7"] = sf::Key::Code::Num7;
					key["Num8"] = sf::Key::Code::Num8;
					key["Num9"] = sf::Key::Code::Num9;
					key["Escape"] = sf::Key::Code::Escape;
					key["LControl"] = sf::Key::Code::LControl;
					key["LShift"] = sf::Key::Code::LShift;
					key["LAlt"] = sf::Key::Code::LAlt;
					key["LSystem"] = sf::Key::Code::LSystem;
					key["Menu"] = sf::Key::Code::Menu;
					key["LBracket"] = sf::Key::Code::LBracket;
					key["RBracket"] = sf::Key::Code::RBracket;
					key["SemiColon"] = sf::Key::Code::SemiColon;
					key["Comma"] = sf::Key::Code::Comma;
					key["Period"] = sf::Key::Code::Period;
					key["Quote"] = sf::Key::Code::Quote;
					key["Slash"] = sf::Key::Code::Slash;
					key["BackSlash"] = sf::Key::Code::BackSlash;
					key["Tilde"] = sf::Key::Code::Tilde;
					key["Equal"] = sf::Key::Code::Equal;
					key["Dash"] = sf::Key::Code::Dash;
					key["Space"] = sf::Key::Code::Space;
					key["Return"] = sf::Key::Code::Return;
					key["Back"] = sf::Key::Code::Back;
					key["Tab"] = sf::Key::Code::Tab;
					key["PageUp"] = sf::Key::Code::PageUp;
					key["PageDown"] = sf::Key::Code::PageDown;
					key["End"] = sf::Key::Code::End;
					key["Home"] = sf::Key::Code::Home;
					key["Insert"] = sf::Key::Code::Insert;
					key["Delete"] = sf::Key::Code::Delete;
					key["Add"] = sf::Key::Code::Add;
					key["Subtract"] = sf::Key::Code::Subtract;
					key["Multiply"] = sf::Key::Code::Multiply;
					key["Divide"] = sf::Key::Code::Divide;
					key["Left"] = sf::Key::Code::Left;
					key["Right"] = sf::Key::Code::Right;
					key["Up"] = sf::Key::Code::Up;
					key["Down"] = sf::Key::Code::Down;
					key["Numpad0"] = sf::Key::Code::Numpad0;
					key["Numpad1"] = sf::Key::Code::Numpad1;
					key["Numpad2"] = sf::Key::Code::Numpad2;
					key["Numpad3"] = sf::Key::Code::Numpad3;
					key["Numpad4"] = sf::Key::Code::Numpad4;
					key["Numpad5"] = sf::Key::Code::Numpad5;
					key["Numpad6"] = sf::Key::Code::Numpad6;
					key["Numpad7"] = sf::Key::Code::Numpad7;
					key["Numpad8"] = sf::Key::Code::Numpad8;
					key["Numpad9"] = sf::Key::Code::Numpad9;
					key["F1"] = sf::Key::Code::F1;
					key["F2"] = sf::Key::Code::F2;
					key["F3"] = sf::Key::Code::F3;
					key["F4"] = sf::Key::Code::F4;
					key["F5"] = sf::Key::Code::F5;
					key["F6"] = sf::Key::Code::F6;
					key["F7"] = sf::Key::Code::F7;
					key["F8"] = sf::Key::Code::F8;
					key["F9"] = sf::Key::Code::F9;
					key["F10"] = sf::Key::Code::F10;
					key["F11"] = sf::Key::Code::F11;
					key["F12"] = sf::Key::Code::F12;
					key["F13"] = sf::Key::Code::F13;
					key["F14"] = sf::Key::Code::F14;
					key["F15"] = sf::Key::Code::F15;
					key["Pause"] = sf::Key::Code::Pause;
					key["Count"] = sf::Key::Code::Count;
					globals(lua)[ns.c_str()]["Key"] = newtable(lua);
					globals(lua)[ns.c_str()]["Key"]["Code"] = key;

					object button = newtable(lua);
					button["Left"] = sf::Mouse::Button::Left;
					button["Right"] = sf::Mouse::Button::Right;
					button["Middle"] = sf::Mouse::Button::Middle;
					button["XButton1"] = sf::Mouse::Button::XButton1;
					button["XButton2"] = sf::Mouse::Button::XButton2;
					button["ButtonCount"] = sf::Mouse::Button::ButtonCount;
					globals(lua)[ns.c_str()]["Mouse"] = newtable(lua);
					globals(lua)[ns.c_str()]["Mouse"]["Button"] = button;

					object joy = newtable(lua);
					joy["AxisX"] = sf::Joy::Axis::AxisX;
					joy["AxisY"] = sf::Joy::Axis::AxisY;
					joy["AxisZ"] = sf::Joy::Axis::AxisZ;
					joy["AxisR"] = sf::Joy::Axis::AxisR;
					joy["AxisU"] = sf::Joy::Axis::AxisU;
					joy["AxisV"] = sf::Joy::Axis::AxisV;
					joy["AxisPOV"] = sf::Joy::Axis::AxisPOV;
					joy["AxisCount"] = sf::Joy::Axis::AxisCount;
					globals(lua)[ns.c_str()]["Joy"] = newtable(lua);
					globals(lua)[ns.c_str()]["Joy"]["Axis"] = joy;
					globals(lua)[ns.c_str()]["Joy"]["Count"] = sf::Joy::Count;
					globals(lua)[ns.c_str()]["Joy"]["ButtonCount"] = sf::Joy::ButtonCount;

					object eventtype = newtable(lua);
					eventtype["Closed"] = sf::Event::EventType::Closed;
					eventtype["Resized"] = sf::Event::EventType::Resized;
					eventtype["LostFocus"] = sf::Event::EventType::LostFocus;
					eventtype["GainedFocus"] = sf::Event::EventType::GainedFocus;
					eventtype["TextEntered"] = sf::Event::EventType::TextEntered;
					eventtype["KeyPressed"] = sf::Event::EventType::KeyPressed;
					eventtype["KeyReleased"] = sf::Event::EventType::KeyReleased;
					eventtype["MouseWheelMoved"] = sf::Event::EventType::MouseWheelMoved;
					eventtype["MouseButtonPressed"] = sf::Event::EventType::MouseButtonPressed;
					eventtype["MouseButtonReleased"] = sf::Event::EventType::MouseButtonReleased;
					eventtype["MouseMoved"] = sf::Event::EventType::MouseMoved;
					eventtype["MouseEntered"] = sf::Event::EventType::MouseEntered;
					eventtype["MouseLeft"] = sf::Event::EventType::MouseLeft;
					eventtype["JoyButtonPressed"] = sf::Event::EventType::JoyButtonPressed;
					eventtype["JoyButtonReleased"] = sf::Event::EventType::JoyButtonReleased;
					eventtype["JoyMoved"] = sf::Event::EventType::JoyMoved;
					eventtype["Count"] = sf::Event::EventType::Count;
					globals(lua)[ns.c_str()]["Event"]["EventType"] = eventtype;
			}
				
			void BInput(lua_State* lua, const std::string& ns)
			{
				module(lua, ns.c_str())
					[
						class_<sf::Input>("Input")
							.def(constructor<>())
							.def("IsKeyDown", &sf::Input::IsKeyDown)
							.def("IsMouseButtonDown", &sf::Input::IsMouseButtonDown)
							.def("IsJoystickButtonDown", &sf::Input::IsJoystickButtonDown)
							.def("GetMouseX", &sf::Input::GetMouseX)
							.def("GetMouseY", &sf::Input::GetMouseY)
							.def("GetJoystickAxis", &sf::Input::GetJoystickAxis)
					];
			//Joystick.hpp
			}
				
			void BVideoMode(lua_State* lua, const std::string& ns)
			{
				module(lua, ns.c_str())
					[
						class_<sf::VideoMode>("VideoMode")
							.def(constructor<>())
							.def(constructor<int, int, unsigned int>())
							.def("IsValid", &sf::VideoMode::IsValid)
							.def("GetDesktopMode", &sf::VideoModeGetDesktopMode)
							.def("GetFullscreenModes", &sf::VideoModeGetFullscreenModes)
							.def_readwrite("Width", &sf::VideoMode::Width)
							.def_readwrite("Height", &sf::VideoMode::Height)
							.def_readwrite("BitsPerPixel", &sf::VideoMode::BitsPerPixel)
					];
			}
				
			void BWindow(lua_State* lua, const std::string& ns)
			{
				module(lua, ns.c_str())
					[
						class_<sf::Window>("Window")
							.enum_("Style")
							[
								value("None", sf::Style::None),
								value("Titlebar", sf::Style::Titlebar),
								value("Resize", sf::Style::Resize),
								value("Close", sf::Style::Close),
								value("Fullscreen", sf::Style::Fullscreen)
							]
							.def(constructor<>())
							.def(constructor<sf::VideoMode, const std::string&, unsigned long, const sf::ContextSettings&>())
							.def(constructor<sf::WindowHandle, const sf::ContextSettings&>())
							.def("Create", (void(sf::Window::*)(sf::VideoMode, const std::string&, unsigned long, const sf::ContextSettings&))&sf::Window::Create)
							.def("Create", (void(sf::Window::*)(sf::WindowHandle, const sf::ContextSettings&))&sf::Window::Create)
							.def("Close", &sf::Window::Close)
							.def("IsOpened", &sf::Window::IsOpened)
							.def("GetWidth", &sf::Window::GetWidth)
							.def("GetHeight", &sf::Window::GetHeight)
							.def("GetSettings", &sf::Window::GetSettings)
							.def("GetEvent", &sf::Window::GetEvent)
							.def("WaitEvent", &sf::Window::WaitEvent)
							.def("UseVerticalSync", &sf::Window::UseVerticalSync)
							.def("ShowMouseCursor", &sf::Window::ShowMouseCursor)
							.def("SetCursorPosition", &sf::Window::SetCursorPosition)
							.def("SetPosition", &sf::Window::SetPosition)
							.def("SetSize", &sf::Window::SetSize)
							.def("SetTitle", &sf::Window::SetTitle)
							.def("Show", &sf::Window::Show)
							.def("EnableKeyRepeat", &sf::Window::EnableKeyRepeat)
							.def("SetIcon", &sf::Window::SetIcon)
							.def("SetActive", &sf::Window::SetActive)
							.def("Display", &sf::Window::Display)
							.def("GetInput", &sf::Window::GetInput)
							.def("SetFramerateLimit", &sf::Window::SetFramerateLimit)
							.def("GetFrameTime", &sf::Window::GetFrameTime)
							.def("SetJoystickThreshold", &sf::Window::SetJoystickThreshold)
							.def("GetSystemHandle", &sf::Window::GetSystemHandle)
					];
			}
				
			void BWindowHandle(lua_State* lua, const std::string& ns)
			{
			}
				
			void BWindowStyle(lua_State* lua, const std::string& ns)
			{
			}
				
			void BOpenGL(lua_State* lua, const std::string& ns)
			{
			}
				
			void Bind(lua_State* lua, const std::string& ns)
			{
				open(lua);
				BContextSettings(lua, ns);
				BEvent(lua, ns);
				BInput(lua, ns);
				BVideoMode(lua, ns);
				BWindow(lua, ns);
				BWindowHandle(lua, ns);
				BWindowStyle(lua, ns);
				BOpenGL(lua, ns);
			}				
		}
	}		
}